home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / utilsys / rss14gmd.lha / RSys_1.4gmd / C / SaveWindow.c < prev    next >
C/C++ Source or Header  |  1996-05-04  |  21KB  |  967 lines

  1. /*
  2.    ***************************************************************************
  3.    *
  4.    * Datei:
  5.    *      RSysSaveWindow.c
  6.    *
  7.    * Inhalt:
  8.    *
  9.    *      --- Globale Routinen ---
  10.    *
  11.    *    void SaveWindows ( void );
  12.    *
  13.    *      --- Lokale  Routinen ---
  14.    *
  15.    *    static BYTE PutANNO ( IFFHANDLE *Handle );
  16.    *    static BYTE PutBMHD ( IFFHANDLE *Handle , WINDOW *Window , UBYTE Compression );
  17.    *    static BYTE PutBODY ( IFFHANDLE *Handle , BITMAP *BitMap , UBYTE Compression );
  18.    *    static BYTE PutCAMG ( IFFHANDLE *Handle , VIEWPORT *VPort );
  19.    *    static BYTE PutCMAP ( IFFHANDLE *Handle , VIEWPORT *VPort );
  20.    *    static BYTE SaveWindow ( STRPTR Name , WINDOW *Window );
  21.    *    static int OpenSaveAWindowWindow ( void );
  22.    *    static LONG PackRow ( PLANEPTR *SourcePtr ,  PLANEPTR Destination , LONG RowSize );
  23.    *    static PLANEPTR PutDump (  PLANEPTR Destination ,  LONG Count );
  24.    *    static PLANEPTR PutRun (  PLANEPTR Destination , LONG Count , WORD Char );
  25.    *    static void CreateWinList ( int count );
  26.    *    static void ResetWinList ( void );
  27.    *
  28.    * Bemerkungen:
  29.    *      Erzeugen einer IFF-Datei aus einem Window.
  30.    *
  31.    * Erstellungsdatum:
  32.    *      07-Jan-93     Rolf Böhme
  33.    *
  34.    * Änderungen:
  35.    *      07-Jan-93     Rolf Böhme        Erstellung
  36.    *
  37.    ***************************************************************************
  38.  */
  39.  
  40. #include "RSys.h"
  41. #include "protos.h"
  42.  
  43.  /*
  44.   * Diese Routinen habe ich wieder mal aus der
  45.   * "Quellen-Fundgrube" von TERM entnommen.  Danke Olaf!        Aber
  46.   * einiges war leider falsch :-)
  47.   */
  48.  
  49.  
  50.  /* Local packer data. */
  51.  
  52. static LONG PackedBytes;
  53. static BYTE Buffer[MAXDAT + 1];
  54.  
  55.  /* PutDump( PLANEPTR Destination, LONG Count):
  56.  
  57.   *     Output a byte dump.
  58.   */
  59.  
  60. static PLANEPTR
  61. PutDump (PLANEPTR Destination, LONG Count)
  62. {
  63.   PLANEPTR Source = (PLANEPTR) Buffer;
  64.  
  65.   *Destination++ = Count - 1;
  66.   PackedBytes += Count + 1;
  67.  
  68.   while (Count--)
  69.     *Destination++ = *Source++;
  70.  
  71.   return Destination;
  72. }
  73.  
  74.  /* PutRun( PLANEPTR Destination,LONG Count,WORD Char):
  75.  
  76.   *     Output a byte run.
  77.   */
  78.  
  79. static PLANEPTR
  80. PutRun (PLANEPTR Destination, LONG Count, WORD Char)
  81. {
  82.   *Destination++ = -(Count - 1);
  83.   *Destination++ = Char;
  84.   PackedBytes += 2;
  85.  
  86.   return Destination;
  87. }
  88.  
  89.  /* PackRow(PLANEPTR *SourcePtr, PLANEPTR Destination,LONG RowSize):
  90.  
  91.   *     Pack a row of bitmap data using ByteRun compression,
  92.   *     based on the original "EA IFF 85" pack.c example code.
  93.   */
  94.  
  95. static LONG
  96. PackRow (PLANEPTR * SourcePtr, PLANEPTR Destination, LONG RowSize)
  97. {
  98.   PLANEPTR Source = *SourcePtr;
  99.  
  100.   WORD Buffered = 1, RunStart = 0;
  101.   BYTE Mode = DUMP, LastChar, Char;
  102.  
  103.   PackedBytes = 0;
  104.  
  105.   Buffer[0] = LastChar = Char = *Source++;
  106.  
  107.   RowSize--;
  108.  
  109.   while (RowSize--)
  110.     {
  111.       Buffer[Buffered++] = Char = *Source++;
  112.  
  113.       if (Mode)
  114.     {
  115.       if ((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  116.         {
  117.           Destination = PutRun (Destination, Buffered - 1 - RunStart, LastChar);
  118.           Buffer[0] = Char;
  119.           Buffered = 1;
  120.           RunStart = 0;
  121.           Mode = DUMP;
  122.         }
  123.     }
  124.       else
  125.     {
  126.       if (Buffered > MAXDAT)
  127.         {
  128.           Destination = PutDump (Destination, Buffered - 1);
  129.           Buffer[0] = Char;
  130.           Buffered = 1;
  131.           RunStart = 0;
  132.         }
  133.       else
  134.         {
  135.           if (Char == LastChar)
  136.         {
  137.           if (Buffered - RunStart >= MINRUN)
  138.             {
  139.               if (RunStart)
  140.             Destination = PutDump (Destination, (LONG) RunStart);
  141.  
  142.               Mode = RUN;
  143.             }
  144.           else
  145.             {
  146.               if (!RunStart)
  147.             Mode = RUN;
  148.             }
  149.         }
  150.           else
  151.         RunStart = Buffered - 1;
  152.         }
  153.     }
  154.  
  155.       LastChar = Char;
  156.     }
  157.  
  158.   if (Mode)
  159.     PutRun (Destination, Buffered - RunStart, LastChar);
  160.   else
  161.     PutDump (Destination, (LONG) Buffered);
  162.  
  163.   *SourcePtr = Source;
  164.  
  165.   return PackedBytes;
  166. }
  167.  
  168.  /* PutANNO(IFFHANDLE *Handle):
  169.  
  170.   *     Output `ANNO' chunk.
  171.   */
  172.  
  173. static BYTE
  174. PutANNO (IFFHANDLE * Handle)
  175. {
  176.   WORD Len;
  177.  
  178.   Len = strlen (&gmdv[1]);
  179.  
  180.   /* Push the `ANNO' chunk on the stack. */
  181.  
  182.   if (!PushChunk (Handle, 0, ID_ANNO, (long) Len))
  183.     {
  184.       /* Write the creator string. */
  185.  
  186.       if (WriteChunkBytes (Handle, &gmdv[1], (long) Len) == Len)
  187.     {
  188.       /* Pop the `ANNO' chunk. */
  189.  
  190.       if (!PopChunk (Handle))
  191.         return TRUE;
  192.     }
  193.     }
  194.  
  195.   return FALSE;
  196. }
  197.  
  198.  /* PutBMHD():
  199.  
  200.   *     Output `BMHD' chunk.
  201.   */
  202.  
  203. static BYTE
  204. PutBMHD (IFFHANDLE * Handle, WINDOW * Window, UBYTE Compression)
  205. {
  206.   DISPLAYINFO DisplayInfo;
  207.  
  208.   /* Get the display aspect ratio. */
  209.  
  210.   if (GetDisplayInfoData (NULL,
  211.               (APTR) & DisplayInfo,
  212.               sizeof (DISPLAYINFO),
  213.               DTAG_DISP,
  214.               GetVPModeID (&Window->WScreen->ViewPort)))
  215.     {
  216.       RSYS_BitMapHeader Header;
  217.  
  218.       /* Fill in the bitmap header. */
  219.  
  220.       Header.w = Window->Width;
  221.       Header.h = Window->Height;
  222.       Header.pageWidth = Window /*-> WScreen*/ ->Width;
  223.       Header.pageHeight = Window /*-> WScreen*/ ->Height;
  224.       Header.x = Window->LeftEdge;
  225.       Header.y = Window->TopEdge;
  226.       Header.nPlanes = Window /*-> WScreen*/ ->RPort->BitMap->Depth;
  227.       Header.masking = mskNone;
  228.       Header.compression = Compression;
  229.       Header.pad1 = 0;
  230.       Header.transparentColor = 0;
  231.       Header.xAspect = DisplayInfo.Resolution.x;
  232.       Header.yAspect = DisplayInfo.Resolution.y;
  233.  
  234.       /* Push the `BMHD' chunk on the stack. */
  235.  
  236.       if (!PushChunk (Handle, 0, ID_BMHD, sizeof (RSYS_BitMapHeader)))
  237.     {
  238.       /* Write the bitmap header. */
  239.  
  240.       if (WriteChunkBytes (Handle, &Header, sizeof (RSYS_BitMapHeader)) == sizeof (RSYS_BitMapHeader))
  241.         {
  242.           /* Pop the `BMHD' chunk. */
  243.  
  244.           if (!PopChunk (Handle))
  245.         return TRUE;
  246.         }
  247.     }
  248.     }
  249.  
  250.   return FALSE;
  251. }
  252.  
  253.  /* PutCMAP(IFFHANDLE *Handle,VIEWPORT *VPort):
  254.  
  255.   *     Output `CMAP' chunk, only 4-bit colour s
  256.   *     are supported so far.
  257.   */
  258.  
  259. static BYTE
  260. PutCMAP (IFFHANDLE * Handle, VIEWPORT * VPort)
  261. {
  262.   /* Push the `CMAP' chunk on the stack. */
  263.  
  264.   if (!PushChunk (Handle, 0, ID_CMAP, 3 * VPort->ColorMap->Count))
  265.     {
  266.       RSYS_ColorRegister Colour;
  267.       LONG i;
  268.       ULONG Value, R, G, B;
  269.  
  270.       /* Read and convert all the
  271.        * ColorMap entries (4 bit colour
  272.        * components only).
  273.        */
  274.  
  275.       for (i = 0; i < VPort->ColorMap->Count; i++)
  276.     {
  277.       /* Read colour value. */
  278.  
  279.       Value = GetRGB4 (VPort->ColorMap, i);
  280.  
  281.       /* Split the value into components. */
  282.  
  283.       R = (Value >> 8) & 0xF;
  284.       G = (Value >> 4) & 0xF;
  285.       B = (Value) & 0xF;
  286.  
  287.       /* Store the colour components. */
  288.  
  289.       Colour.red = (R << 4) | R;
  290.       Colour.green = (G << 4) | G;
  291.       Colour.blue = (B << 4) | B;
  292.  
  293.       /* Write the colours. */
  294.  
  295.       if (WriteChunkBytes (Handle, &Colour, 3) != 3)
  296.         return (FALSE);
  297.     }
  298.  
  299.       /* Pop the `CMAP' chunk. */
  300.  
  301.       if (!PopChunk (Handle))
  302.     return TRUE;
  303.     }
  304.  
  305.   return FALSE;
  306. }
  307.  
  308.  /* PutCAMG(IFFHANDLE *Handle,VIEWPORT *VPort):
  309.  
  310.   *     Output `CAMG' chunk.
  311.   */
  312.  
  313. static BYTE
  314. PutCAMG (IFFHANDLE * Handle, VIEWPORT * VPort)
  315. {
  316.   if (!PushChunk (Handle, 0, ID_CAMG, sizeof (ULONG)))
  317.     {
  318.       ULONG ViewModes = GetVPModeID (VPort), ulongsize = sizeof (ULONG);
  319.  
  320.       if (WriteChunkBytes (Handle, &ViewModes, ulongsize) == ulongsize)
  321.     {
  322.       if (!PopChunk (Handle))
  323.         return TRUE;
  324.     }
  325.     }
  326.  
  327.   return FALSE;
  328. }
  329.  
  330.  /* PutBODY(IFFHANDLE *Handle)
  331.  
  332.   *     Output `BODY' chunk.
  333.   */
  334.  
  335. static BYTE
  336. PutBODY (IFFHANDLE * Handle, BITMAP * BitMap, UBYTE Compression)
  337. {
  338.   BYTE Success = FALSE;
  339.  
  340.   PLANEPTR *Planes;
  341.  
  342.   /* Allocate temporary bitplane pointers. */
  343.  
  344.   if (Planes = (PLANEPTR *) MyAllocVec (BitMap->Depth * sizeof (PLANEPTR *), MEMF_ANY | MEMF_CLEAR, NO_KILL))
  345.     {
  346.       LONG i;
  347.  
  348.       /* Copy the bitplane pointers. */
  349.  
  350.       for (i = 0; i < BitMap->Depth; i++)
  351.     Planes[i] = BitMap->Planes[i];
  352.  
  353.       /* Are we to compress the data? */
  354.  
  355.       if (Compression == cmpByteRun1)
  356.     {
  357.       PLANEPTR PackBuffer;
  358.  
  359.       /* Allocate line compression buffer. */
  360.  
  361.       if (PackBuffer = (PLANEPTR) MyAllocVec (BitMap->BytesPerRow * 2, MEMF_ANY, NO_KILL))
  362.         {
  363.           /* Push the `BODY' chunk on the stack. */
  364.  
  365.           if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
  366.         {
  367.           LONG PackedBytes, j;
  368.  
  369.           /* So far, we are quite successful,
  370.            * any write access to fail will
  371.            * cause `Success' to drop to FALSE.
  372.            */
  373.  
  374.           Success = TRUE;
  375.  
  376.           /* Compress all the rows. */
  377.  
  378.           for (i = 0; Success && i < BitMap->Rows; i++)
  379.             {
  380.               /* Compress all the planes. */
  381.  
  382.               for (j = 0; Success && j < BitMap->Depth; j++)
  383.             {
  384.               /* Do the compression. */
  385.  
  386.               PackedBytes = PackRow (&Planes[j], PackBuffer, (LONG) BitMap->BytesPerRow);
  387.  
  388.               /* Write the compressed data. */
  389.  
  390.               if (WriteChunkBytes (Handle, PackBuffer, PackedBytes) != PackedBytes)
  391.                 Success = FALSE;
  392.             }
  393.             }
  394.  
  395.           /* Pop the `BODY' chunk. */
  396.  
  397.           if (PopChunk (Handle))
  398.             Success = FALSE;
  399.         }
  400.  
  401.           /* Free the line compression buffer. */
  402.  
  403.           MyFreeVec (PackBuffer);
  404.         }
  405.     }
  406.       else
  407.     {
  408.       /* Push the `BODY' chunk on the stack. */
  409.  
  410.       if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
  411.         {
  412.           LONG j;
  413.  
  414.           /* So far, we are quite successful,
  415.            * any write access to fail will
  416.            * cause `Success' to drop to FALSE.
  417.            */
  418.  
  419.           Success = TRUE;
  420.  
  421.           /* Compress all the rows. */
  422.  
  423.           for (i = 0; Success && i < BitMap->Rows; i++)
  424.         {
  425.           /* Compress all the planes. */
  426.  
  427.           for (j = 0; Success && j < BitMap->Depth; j++)
  428.             {
  429.               /* Write the row. */
  430.  
  431.               if (WriteChunkBytes (Handle, Planes[j], (long) BitMap->BytesPerRow) != BitMap->BytesPerRow)
  432.             Success = FALSE;
  433.               else
  434.             Planes[j] += BitMap->BytesPerRow;
  435.             }
  436.         }
  437.  
  438.           /* Pop the `BODY' chunk. */
  439.  
  440.           if (PopChunk (Handle))
  441.         Success = FALSE;
  442.         }
  443.     }
  444.  
  445.       /* Free the temporary bitplane pointers. */
  446.  
  447.       MyFreeVec (Planes);
  448.     }
  449.  
  450.   /* Return the result. */
  451.  
  452.   return Success;
  453. }
  454.  
  455.  /* SaveWindow(STRPTR Name,WINDOW *Window):
  456.  
  457.   *     Save the contents of a window to a file.
  458.   */
  459.  
  460. static BYTE
  461. SaveWindow (STRPTR Name, WINDOW * Window)
  462. {
  463.   RASTPORT *RPort;
  464.   BYTE Success = FALSE, NewFile = FALSE;
  465.  
  466.   if (IFFParseBase = OpenLibrary ((STRPTR) "iffparse.library", 0))
  467.     {
  468.       /* Allocate a dummy rastport, we will need only
  469.        * to copy the contents of the window into the
  470.        * bitmap.
  471.        */
  472.  
  473.       if (RPort = (RASTPORT *) MyAllocVec (sizeof (RASTPORT), MEMF_ANY, NO_KILL))
  474.     {
  475.       BITMAP *BitMap;
  476.  
  477.       /* Initialize the rastport with defaults. */
  478.  
  479.       InitRastPort (RPort);
  480.  
  481.       /* Allocate a bitmap. */
  482.  
  483.       if (BitMap = (BITMAP *) MyAllocVec (sizeof (BITMAP), MEMF_ANY, NO_KILL))
  484.         {
  485.           WORD i;
  486.  
  487.           /* Put it into the rastport. */
  488.  
  489.           RPort->BitMap = BitMap;
  490.  
  491.           /* Initialize it with the window dimensions. */
  492.  
  493.           /*
  494.            * An dieser Stelle ist der RastPort des Fensters
  495.            * zu nehmen, NICHT der des Screens, zu dem das
  496.            * Fenster gehört!
  497.            */
  498.           InitBitMap (BitMap,
  499.               (long) Window->RPort->BitMap->Depth,
  500.               (long) (Window->Width),
  501.               (long) Window->Height);
  502.  
  503.           /* Flag success so any allocation
  504.            * to fail in the bitplane allocation
  505.            * loop will indicate failure.
  506.            */
  507.  
  508.           Success = TRUE;
  509.  
  510.           /* Allocate all the bitplanes necessary. */
  511.  
  512.           for (i = 0; Success && i < BitMap->Depth; i++)
  513.         {
  514.           if (!(BitMap->Planes[i] = AllocRaster ((long) Window->Width, (long) Window->Height)))
  515.             Success = FALSE;
  516.         }
  517.  
  518.           /* Did we get all the planes we wanted? */
  519.  
  520.           if (Success)
  521.         {
  522.           IFFHANDLE *Handle;
  523.  
  524.           /* Copy the window contents to the
  525.            * local bitmap.
  526.            */
  527.           if (NOT (Window->Flags & WFLG_BACKDROP))
  528.             WindowToFront (Window);
  529.  
  530.           Delay (10);
  531.  
  532.           /*
  533.            * ClipBlit() arbeitet nicht korrekt! Ich habe
  534.            * die Routine durch BltBitMap() ersetzt
  535.            */
  536.           /*
  537.            * ClipBlit(Window -> RPort,0,0,RPort,0,0,(long)Window -> Width,(long)Window -> Height,0xC0);
  538.            */
  539.  
  540.           BltBitMap (Window->RPort->BitMap,
  541.             (long) Window->LeftEdge, (long) Window->TopEdge, BitMap,
  542.                  0, 0, (long) Window->Width, (long) Window->Height, 0xC0, 0xFF, NULL);
  543.  
  544.           /* Reset the success indicator. */
  545.  
  546.           Success = FALSE;
  547.  
  548.           /* Allocate an iff handle. */
  549.  
  550.           if (Handle = AllocIFF ())
  551.             {
  552.               /* Open a file for write access. */
  553.  
  554.               if (Handle->iff_Stream = Open (Name, MODE_NEWFILE))
  555.             {
  556.               /* Remember that we succeeded
  557.                * in creating a new file.
  558.                */
  559.  
  560.               NewFile = TRUE;
  561.  
  562.               /* Tell iffparse.library that it's
  563.                * a plain AmigaDOS file handle.
  564.                */
  565.  
  566.               InitIFFasDOS (Handle);
  567.  
  568.               /* Open the file for writing. */
  569.  
  570.               if (!OpenIFF (Handle, IFFF_WRITE))
  571.                 {
  572.                   /* Push parent chunk on the
  573.                    * stack.
  574.                    */
  575.  
  576.                   if (!PushChunk (Handle, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN))
  577.                 {
  578.                   /* Output all the chunk data. */
  579.  
  580.                   if (PutANNO (Handle))
  581.                     {
  582.                       UBYTE Compression;
  583.  
  584.                       /* Don't compress the bitmap if
  585.                        * isn't really worth it.
  586.                        */
  587.                       if (BitMap->BytesPerRow > 4)
  588.                     Compression = cmpByteRun1;
  589.                       else
  590.                     Compression = cmpNone;
  591.  
  592.                       if (PutBMHD (Handle, Window, Compression))
  593.                     {
  594.                       if (PutCMAP (Handle, &Window->WScreen->ViewPort))
  595.                         {
  596.                           if (PutCAMG (Handle, &Window->WScreen->ViewPort))
  597.                         {
  598.                           if (PutBODY (Handle, BitMap, Compression))
  599.                             {
  600.                               /* Pop the parent chunk
  601.                                * from the stack.
  602.                                */
  603.  
  604.                               if (!PopChunk (Handle))
  605.                             Success = TRUE;
  606.                             }
  607.                         }
  608.                         }
  609.                     }
  610.                     }
  611.                 }
  612.  
  613.                   /* Close the iff handle. */
  614.  
  615.                   CloseIFF (Handle);
  616.                 }
  617.  
  618.               /* Close the file. */
  619.  
  620.               if (!Close (Handle->iff_Stream))
  621.                 Success = FALSE;
  622.             }
  623.  
  624.               /* Free the iff handle. */
  625.  
  626.               FreeIFF (Handle);
  627.             }
  628.         }
  629.  
  630.           /* Free all bitplanes. */
  631.  
  632.           for (i = 0; i < BitMap->Depth; i++)
  633.         {
  634.           if (BitMap->Planes[i])
  635.             FreeRaster (BitMap->Planes[i], (long) Window->Width, (long) Window->Height);
  636.         }
  637.  
  638.           /* Free the bitmap. */
  639.  
  640.           MyFreeVec (BitMap);
  641.         }
  642.  
  643.       /* Free the rastport. */
  644.  
  645.       MyFreeVec (RPort);
  646.     }
  647.  
  648.       /* If successful, clear the `executable' bit. */
  649.  
  650.       if (Success)
  651.     SetProtection (Name, FIBF_EXECUTE);
  652.       else
  653.     {
  654.       /* Delete the remains of the file. */
  655.  
  656.       if (NewFile)
  657.         DeleteFile (Name);
  658.     }
  659.  
  660.       CloseLibrary (IFFParseBase);
  661.     }
  662.   else
  663.     Success = FALSE;
  664.  
  665.   /* Return the result. */
  666.  
  667.   return Success;
  668. }
  669.  
  670. RSYS_winlist *windows = NULL;
  671.  
  672. LIST WinList;
  673.  
  674. static WINDOW *SaveAWindowWnd = NULL;
  675. static GADGET *SaveAWindowGList = NULL;
  676. static GADGET *SaveAWindowGadgets[3];
  677. static UWORD SaveAWindowLeft = 178;
  678. static UWORD SaveAWindowTop = 38;
  679. static UWORD SaveAWindowWidth = 258;
  680. static UWORD SaveAWindowHeight = 121;
  681. static UBYTE SaveAWindowWdt[100];    /*GMD */
  682.  
  683. static UWORD SaveAWindowGTypes[] =
  684. {
  685.   LISTVIEW_KIND,
  686.   BUTTON_KIND,
  687.   BUTTON_KIND
  688. };
  689.  
  690. static NEWGADGET SaveAWindowNGad[] =
  691. {
  692.   8, 18, 241, 80, (UBYTE *) "Windows", NULL, GD_WindowsLVGad, PLACETEXT_ABOVE, NULL, NULL,
  693.   8, 103, 113, 13, (UBYTE *) "IFF File", NULL, GD_SaveIFFGad, PLACETEXT_IN, NULL, NULL,
  694.   128, 103, 121, 13, (UBYTE *) "Rescan windows", NULL, GD_ResetWinGad, PLACETEXT_IN, NULL, NULL
  695. };
  696.  
  697. static ULONG *SaveAWindowGTags[] =
  698. {
  699.   (ULONG *) (GTLV_ShowSelected), (ULONG *) NULL, (ULONG *) (GTLV_Labels), (ULONG *) & WinList, (ULONG *) (TAG_DONE),
  700.   (ULONG *) (TAG_DONE),
  701.   (ULONG *) (TAG_DONE)
  702. };
  703.  
  704.  /*
  705.   * OpenSaveAWindowWindow() öffnet ein Fenster mit einem
  706.   * ListView und zwei Gadgets zu Auswahl eines zu speichernden
  707.   * Fensters
  708.   */
  709. static int
  710. OpenSaveAWindowWindow (void)
  711. {
  712.   NEWGADGET ng;
  713.   GADGET *g;
  714.   UWORD lc, tc;
  715.   UWORD wleft = SaveAWindowLeft, wtop = SaveAWindowTop, ww, wh;
  716.   int gl[] =
  717.   {GD_WindowsLVGad - GD_WindowsLVGad};
  718.  
  719.   AdjustWindowDimensions (Scr, SaveAWindowLeft, SaveAWindowTop, SaveAWindowWidth, SaveAWindowHeight,
  720.               &wleft, &wtop, &ww, &wh);
  721.  
  722.   if (!(g = CreateContext (&SaveAWindowGList)))
  723.     return 1L;
  724.  
  725.   for (lc = 0, tc = 0; lc < SaveAWindow_CNT; lc++)
  726.     {
  727.       CopyMem ((char *) &SaveAWindowNGad[lc], (char *) &ng, (long) sizeof (NEWGADGET));
  728.  
  729.       ng.ng_VisualInfo = VisualInfo;
  730.       ng.ng_TextAttr = Font;
  731.       ng.ng_LeftEdge = OffX + ComputeX (ng.ng_LeftEdge);
  732.       ng.ng_TopEdge = OffY + ComputeY (ng.ng_TopEdge);
  733.       ng.ng_Width = ComputeX (ng.ng_Width);
  734.       ng.ng_Height = ComputeY (ng.ng_Height);
  735.  
  736.       SaveAWindowGadgets[lc] = g = CreateGadgetA ((ULONG) SaveAWindowGTypes[lc], g, &ng, (TAGITEM *) & SaveAWindowGTags[tc]);
  737.  
  738.       makelabelvisible (SaveAWindowGadgets[lc]);
  739.  
  740.       while (SaveAWindowGTags[tc])
  741.     tc += 2;
  742.       tc++;
  743.  
  744.       if (NOT g)
  745.     return 2L;
  746.     }
  747.  
  748.   strcpy (SaveAWindowWdt, get_vers (" - Save window"));        /*GMD */
  749.  
  750.   if (!(SaveAWindowWnd = OpenWindowTags (NULL,
  751.                      WA_Left, wleft,
  752.                      WA_Top, wtop,
  753.                      WA_Width, ww,
  754.                      WA_Height, wh,
  755.                      WA_IDCMP, LISTVIEWIDCMP |
  756.                      BUTTONIDCMP |
  757.                      IDCMP_CLOSEWINDOW |
  758.                      IDCMP_VANILLAKEY |
  759.                      IDCMP_REFRESHWINDOW,
  760.                      WA_Flags, WFLG_DRAGBAR |
  761.                      WFLG_DEPTHGADGET |
  762.                      WFLG_CLOSEGADGET |
  763.                      WFLG_SMART_REFRESH |
  764.                      WFLG_ACTIVATE |
  765.                      WFLG_RMBTRAP,
  766.                      WA_Title, SaveAWindowWdt,
  767.                      WA_PubScreenFallBack, TRUE,
  768.                      WA_PubScreen, Scr,
  769.                      TAG_DONE)))
  770.     return 4L;
  771.  
  772.   RefreshRastPort (SaveAWindowWnd, SaveAWindowGadgets, gl, 1, FALSE, SaveAWindowGList);
  773.  
  774.   return NULL;
  775. }
  776.  
  777.  /*
  778.   * CreateWinList() erzeugt eine Liste von Fenstertiteln und
  779.   * Adressen
  780.   */
  781. static void
  782. CreateWinList (int count)
  783. {
  784.   ULONG lock;
  785.   WINDOW *win;
  786.   SCREEN *scr;
  787.   char help[MAXFULLNAME];
  788.   int i = 0;
  789.  
  790.   DPOS;
  791.   MyFreeVec (windows);
  792.  
  793.   windows = (RSYS_winlist *) MyAllocVec (count * sizeof (RSYS_winlist),
  794.                      MEMF_ANY | MEMF_CLEAR, KILL);
  795.  
  796.   lock = LockIBase (NULL);
  797.  
  798.   for (scr = IntuitionBase->FirstScreen; scr && (i < count); scr = scr->NextScreen)
  799.     for (win = scr->FirstWindow; win && (i < count); win = win->NextWindow)
  800.       {
  801.     windows[i].node.ln_Name = windows[i].name;
  802.     windows[i].node.ln_Type = NT_USER;
  803.  
  804.     windows[i].win = win;
  805.  
  806.     if ((char *) win->Title)
  807.       strncpy (help, (char *) win->Title, MAXFULLNAME - 1);
  808.     else
  809.       help[0] = STRINGEND;
  810.  
  811.     sprintf (windows[i].name, "0x%08lX %s", windows[i].win, help);
  812.  
  813.     i++;
  814.       }
  815.  
  816.   UnlockIBase (lock);
  817.  
  818.   for (i = 0; i < count; i++)
  819.     AddTail (&WinList, &windows[i].node);
  820.  
  821.   return;
  822. }
  823.  
  824.  /*
  825.   * ResetWinList() erneuert die Window-Liste
  826.   */
  827. static void
  828. ResetWinList (void)
  829. {
  830.   int cntwin;
  831.  
  832.   DPOS;
  833.   InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], NULL, 0);
  834.  
  835.   NewList (&WinList);
  836.  
  837.   cntwin = CountIntuiObjects ((int) WINDOWS);
  838.  
  839.   CreateWinList (cntwin);
  840.  
  841.   InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], &WinList, 0);
  842.  
  843.   EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad], FALSE);
  844.  
  845.   return;
  846. }
  847.  
  848.  /*
  849.   * SaveWindows() bietet eine Benutzeroberfläche an und
  850.   * verwaltet die Benutzereingaben
  851.   */
  852. void
  853. SaveWindows (void)
  854. {
  855.   INTUIMESSAGE *message;
  856.   ULONG class, code;
  857.   APTR object;
  858.   NODE *clickednode = NULL;
  859.   WINDOW *printwin;
  860.   int id;
  861.  
  862.   DPOS;
  863.  
  864.   HandleHelp (MN_SaveWindows);
  865.  
  866.   Flags.quit_sw = 0;
  867.  
  868.   NewList (&WinList);
  869.  
  870.   windows = NULL;
  871.  
  872.   if (OpenASysWindow (OpenSaveAWindowWindow, NO_KILL))
  873.     {
  874.       PrintInfo ("Save windows", SPEAK, 0);
  875.  
  876.       LockMainWindow (WIN_LOCK);
  877.  
  878.       ResetWinList ();
  879.  
  880.       do
  881.     {
  882.       Wait (1L << SaveAWindowWnd->UserPort->mp_SigBit);
  883.  
  884.       while ((message = (INTUIMESSAGE *) GT_GetIMsg (SaveAWindowWnd->UserPort)) != NULL)
  885.         {
  886.           class = message->Class;
  887.           code = message->Code;
  888.           object = message->IAddress;
  889.  
  890.           GT_ReplyIMsg (message);
  891.  
  892.           switch (class)
  893.         {
  894.         case IDCMP_CLOSEWINDOW:
  895.           Flags.quit_sw = 1;
  896.           break;
  897.  
  898.         case IDCMP_GADGETUP:
  899.           id = ((GADGET *) object)->GadgetID;
  900.  
  901.           switch (id)
  902.             {
  903.             case GD_WindowsLVGad:
  904.               if (clickednode = GetNode (&WinList, code))
  905.             EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad],
  906.                       TRUE);
  907.  
  908.               printwin = ((RSYS_winlist *) clickednode)->win;
  909.  
  910.               if (NOT (CheckWindow (printwin)))
  911.             {
  912.               ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);
  913.               clickednode = NULL;
  914.               ResetWinList ();
  915.             }
  916.  
  917.               break;
  918.  
  919.             case GD_SaveIFFGad:
  920.               if (clickednode)
  921.             {
  922.               if (GetFile (SaveAWindowWnd, "RAM:",
  923.                        "RSys-Window.IFF", "#?.IFF",
  924.                        "Select IFF-File for saving Window",
  925.                        "Save"))
  926.                 {
  927.                   printwin = ((RSYS_winlist *) clickednode)->win;
  928.  
  929.                   if (CheckWindow (printwin))
  930.                 {
  931.                   if (NOT (SaveWindow ((STRPTR) _fullpath, printwin)))
  932.                     ErrorHandle (_fullpath, FILE_ERR, WRITE_FAIL, NO_KILL);
  933.                 }
  934.                   else
  935.                 ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);
  936.  
  937.                   ResetWinList ();
  938.                 }
  939.             }
  940.               break;
  941.  
  942.             case GD_ResetWinGad:
  943.               clickednode = NULL;
  944.               ResetWinList ();
  945.               break;
  946.             }
  947.           break;
  948.  
  949.         case IDCMP_VANILLAKEY:
  950.           if ((char) code == ESC)
  951.             Flags.quit_sw = 1;
  952.           break;
  953.         }
  954.         }
  955.     }
  956.       while (NOT (Flags.quit_sw));
  957.  
  958.       CloseASysWindow (&SaveAWindowWnd, &SaveAWindowGList, NULL);
  959.  
  960.       MyFreeVec (windows);
  961.  
  962.       LockMainWindow (WIN_UNLOCK);
  963.     }
  964.  
  965.   return;
  966. }
  967.